package com.rey.plugins

import org.gradle.api.Plugin
import org.gradle.api.Project
import java.io.File
import java.nio.file.Files

class CopyOnAssemblePlugin : Plugin<Project> {
    var ext: Extensions? = null

    override fun apply(p0: Project) {
        println("Applying CopyOnAssemblePlugin.")
        p0.run {
            extensions.add("copyConfigs", Extensions::class.java)
            tasks.register("copyApks") { task ->
                println("Register copyApks task.")
                ext = p0.properties["copyConfigs"] as Extensions?
                ext?.run {
                    dependOn?.let {
                        task.dependsOn(p0.tasks.named(it))
                    }
                    task.doLast {
                        println("Executing task: copyApks.")
                        checkProperties()
                        copyTask()
                    }
                } ?: kotlin.run {
                    println(logString("copyConfigs not specified, skipped."))
                }
            }
        }
    }

    private fun copyTask() {
        val suffixPath = listPaths()
        if (suffixPath.isNotEmpty()) {
            suffixPath.forEach { suffix ->
                doCopyFiles(
                    File(ext!!.srcDir ?: "", suffix),
                    File(ext!!.destDir ?: "")
                )
            }
            return
        }
    }

    private fun doCopyFiles(srcPath: File, destPath: File) {
        if (!srcPath.exists() || srcPath.isDirectory) {
            println("Source directory ${srcPath.path} dose not exist.")
            return
        }

        if (!destPath.exists() || !destPath.isDirectory) {
            destPath.mkdirs()
        }

        val files = srcPath.listFiles() ?: emptyArray<File>()
        files.filter {
            "apk" == it.extension
        }.forEachIndexed { index, srcFile ->
            println("Copy ${index + 1} of ${files.size} in ${srcPath.path}")
            Files.copy(
                srcFile.toPath(),
                File(destPath, if (ext!!.rename.isNullOrBlank()) srcFile.name else ext!!.rename!!).toPath()
            )
        }
    }

    private fun listPaths(): List<String> {
        val flavors = ext!!.flavors
        val buildTypes = ext!!.buildTypes
        val pathList = arrayListOf<String>()
        if (flavors.isNotEmpty()) {
            flavors.forEach { flavor ->
                buildTypes.forEach { type ->
                    pathList.add(flavor + File.separator + type)
                }
            }
        } else if (buildTypes.isNotEmpty()) {
            pathList.addAll(buildTypes)
        }
        return pathList
    }

    private fun checkProperties() {
        if (ext!!.srcDir.isNullOrBlank()) {
            throw Throwable(logString("srcDir is not set."))
        }

        if (ext!!.destDir.isNullOrBlank()) {
            throw Throwable(logString("destDir is not set."))
        }
    }

    private fun logString(msg: String): String = "CopyOnAssemblePlugin: $msg"

    open class Extensions {
        /**
         * ## Rename the file to
         */
        var rename: String? = null

        /**
         * ## Apk buildTypes names
         *
         * debug, release, .etc.
         */
        var buildTypes: Array<String> = arrayOf()

        /**
         * ## Apk build flavors names
         */
        var flavors: Array<String> = arrayOf()

        var srcDir: String? = null

        var destDir: String? = null

        var dependOn: String? = null
    }
}